#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time    : 2018/4/16 17:08
# @Author  : simple0426
# @Email   : istyle.simple@gmail.com
# @File    : fabfile.py
# @Software: PyCharm
# @desc    : 功能如下
# 1.查看系统信息
# 2.部署nginx代码
# 3.回滚nginx代码
# 4.更新nginx配置【更新成功后自动重启，更新失败自动回滚配置】
# 5.查看nginx日志【分主机分项目】
# 6.登陆nginx主机【分主机】

from fabric.api import *
from fabric.context_managers import *
from fabric.contrib.console import prompt
from fabric.colors import *
import os, shutil
import json

env.hosts = ['zj-ops@1.1.1.1', 'zj-web@1.1.1.2']
env.gateway = 'zj-ops@2.2.2.2'
env.passwords = {
    'zj-ops@1.1.1.1:22': '1213456',
    'zj-web@1.1.1.2:22': '1213456',
    'zj-ops@2.2.2.2:22': '1213456',
}
env.roledefs = {
    'web1': ['zj-ops@1.1.1.1'],
    'web2': ['zj-web@1.1.1.2'],
    'webserver': ['zj-ops@1.1.1.1', 'zj-web@1.1.1.2']
}
project_dict = {
    'fop': {'name': 'fop', 'log': 'fop.abc.cn.log'},
    'kop': {'name': 'kop', 'log': 'kop.abc.cn.log'},
    'check': {'name': 'cloud-h5', 'log': 'check.fff.cn.log'},
    'open': {'name': 'cloud', 'log': 'open.fff.cn.log'},
    'www': {'name': 'kingold-web', 'log': 'www.fff.cn.log'},
}


@task
@parallel
def df():
    '''查看所有主机的磁盘信息'''
    print yellow(run('df -h'))

@task
@roles('web1')
def free():
    '''只用于查看web1的内存'''
    run('free -m')

@task
@hosts('zj-web@1.1.1.2')
def uptime():
    '''只用于查看1.1.1.2的负载信息'''
    print green(run('uptime'))

def delete_files(filename):
    '''如果文件或目录存在则删除'''
    dest_file = os.path.join(os.path.expanduser('~'), 'deploy', filename)
    if os.path.exists(dest_file) and os.path.isdir(dest_file):
        shutil.rmtree(dest_file)
    elif os.path.exists(dest_file) and os.path.isfile(dest_file):
        os.remove(dest_file)
    else:
        pass

@runs_once
def tar_code():
    '''本地代码打包'''
    project = prompt('请输入要部署的项目:').strip()
    print yellow('本地代码打包')
    if project not in project_dict.keys():
        abort('请输入正确的项目名称')
    project_name = project_dict[project]['name']
    delete_files(project_name)
    delete_files('%s.tar.gz' % project_name)
    with lcd('~/deploy'):
        local('git clone git@10.10.10.164:kingold_app/%s.git' %  project_name, capture=True)
        local('tar czf %s.tar.gz %s' % (project_name, project_name), capture=True)
    return project

def backup_code(project):
    '''远程备份代码'''
    print yellow('远程备份代码')
    if project not in project_dict.keys():
        abort('请输入正确的项目名称')
    project_name = project_dict[project]['name']
    with cd('~/nginx'):
        with settings(warn_only=True):
            result = run('rsync -az --delete %s/ %s.bak/' % (project_name, project_name), quiet=True)
        if result.succeeded:
            print green('代码备份成功')

def push_code(project):
    """上传代码【传输压缩包】"""
    print yellow('本地上传代码')
    if project not in project_dict.keys():
        abort('请输入正确的项目名称')
    project_name = project_dict[project]['name']
    result = put('~/deploy/%s.tar.gz' % project_name, '~/nginx/%s.tar.gz' % project_name)
    if result.failed:
        abort("上传代码失败！")
    else:
        with cd('~/nginx'):
            run('tar xzf %s.tar.gz' % project_name, quiet=True)
            print green('代码部署成功')

@task
def updateconf():
    '''更新配置文件目录'''
    # 备份
    with cd('nginx'):
        run('rsync -az --delete conf/ conf.bak/')
    # 上传
    result = put('~/deploy/conf', '~/nginx')
    with settings(warn_only=True) and cd('nginx'):
        if result.failed:
            # 回滚
            run('rsync -az --delete conf.bak/ conf/')
            abort('上传失败')
        else:
            res_conf = sudo('~/nginx/sbin/nginx -t', quiet=True)
            # 配置文件有效，重启nginx
            if res_conf.succeeded:
                nginx_count = run('ps aux|grep nginx|grep -v grep|wc -l')
                if nginx_count.stdout == '0':
                    sudo('~/nginx/sbin/nginx')
                    print green('nginx启动成功')
                else:
                    sudo('~/nginx/sbin/nginx -s reload')
                    print green('nginx重启成功')
            else:
                # 配置文件无效，回滚配置
                run('rsync -az --delete conf.bak/ conf/')
                print red(res_conf.stdout)

@task
def rollback():
    '''服务回滚'''
    project = prompt('请输入要回滚的项目:').strip()
    print yellow('代码回滚')
    if project not in project_dict.keys():
        abort('请输入正确的项目名称')
    project_name = project_dict[project]['name']
    with settings(warn_only=True):
        result = run('rsync -az --delete %s.bak/ %s/' % (project_name, project_name), quiet=True)
        if result.succeeded:
            print green('代码回滚成功')

@task
def deploy():
    '''服务部署'''
    project = tar_code()
    backup_code(project)
    push_code(project)

@task
@runs_once
def host():
    '''设置登陆主机'''
    print green(json.dumps(env.hosts, indent=4))
    host = prompt('请输入要登陆的主机')
    env.exclude_hosts.extend(env.hosts)
    for hostname in env.hosts:
        if host in hostname:
            env.exclude_hosts.remove(hostname)

@task
def login():
    '''远程登陆[需设置登陆主机]'''
    open_shell()

@task
def log():
    '''查看日志[需设置登陆主机]'''
    print green(json.dumps(project_dict.keys()))
    project = prompt('请输入要部署的项目:').strip()
    project_log = project_dict[project]['log']
    with cd('~/nginx/logs'):
        run('tail -10f %s' % project_log)

